package serverapp

import (
	"context"
	"fmt"
	"os"
	"time"
	"wanyu/server/engine/version"
	"wanyu/server/engine/wplog"
	"wanyu/server/protogo/public"
	"wanyu/serverlib/monitor"
	"wanyu/serverlib/utils"

	"github.com/golang/protobuf/ptypes/empty"
)

type OnCmdFunc func(cmd string, param string) string

type baseCmd struct {
	callback  OnCmdFunc
	debugAddr string
}

func (bh *baseCmd) GetHealth(ctx context.Context, req *empty.Empty, rsp *public.GetHealthRsp) error {
	if nil != bh.callback {
		fnExit := make(chan bool)
		defer close(fnExit)
		//单独开个协程来执行
		go func() {
			defer func() {
				if err := recover(); nil != err {
					rsp.Health = "执行健康度自检函数捕获到异常，请上环境自行查看"
					wplog.Error("call health func catch a exception, ec = ", err)
					fnExit <- true
				}
			}()

			rsp.Health = bh.callback("/i", "")
			fnExit <- true
		}()

		select {
		case <-fnExit:
		case <-time.After(time.Second * 5):
			rsp.Health = "调用自检函数超时"
		}
	} else {
		rsp.Health = "未设置健康度自检函数"
	}

	pid := os.Getpid()
	cpu, mem, handle := monitor.GetProgressInfo(pid)
	rsp.Cpu = int32(cpu)
	rsp.Memory = int32(mem)
	rsp.Handle = int32(handle)

	return nil
}

func (bh *baseCmd) GetVersion(ctx context.Context, req *empty.Empty, rsp *public.GetVersionRsp) error {
	rsp.ServiceVer = version.SERVICE_VERSION
	rsp.GitVer = version.GIT_VERSION
	rsp.BuildDate = version.BUILD_DATE
	rsp.BuildIp = version.BUILD_IP

	return nil
}

func (bh *baseCmd) GetStack(ctx context.Context, req *empty.Empty, rsp *public.GetStackRsp) error {
	if "" == bh.debugAddr {
		return fmt.Errorf("调试端口为空")
	}

	output, err := utils.ShellCmd(fmt.Sprintf(`curl http://127.0.0.1%s/debug/pprof/goroutine?debug=2`, bh.debugAddr))
	if nil != err {
		return err
	}

	rsp.Buf = output

	return nil
}

func (bh *baseCmd) ServiceCmd(ctx context.Context, req *public.ServiceCmdReq, rsp *public.ServiceCmdRsp) error {
	rsp.Buf = bh.callback(req.Cmd, req.Param)
	return nil
}

func (bh *baseCmd) BakAndRestart(ctx context.Context, req *public.BakAndRestartReq, rsp *public.BakAndRestartRsp) error {
	if "" == req.ServiceFlag {
		rsp.Rsp = []byte("备份服务参数为空，终止后续操作（代理检测）")
		return nil
	}
	wplog.Info("target service = ", req.ServiceFlag)
	output, err := utils.ShellCmd("sh -x /tmp/bakAndRestart.sh " + req.ServiceFlag)
	wplog.Infof("exec bakAndRestart.sh, output = %v, ec = %v", output, err)
	rsp.Rsp = []byte(output)

	return err
}
